package com.mrwang.example.nio.part20191027;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * Scatter / Gather
 * Java NIO内置了对scatter / gather（分散/聚集）的支持。分散/聚集是在用在从Channel读取数据或往Channel写入数据时的概念。
 *
 * 分散读指的是从一个Channel将数据读入多个Buffer。因此，Channel将数据分散到了多个Buffer。
 *
 * 聚集写指的是将多个Buffer的数据写入单个Channel。因此Channel将多个Buffer的数据聚集了起来。
 *
 * 在需要分别处理数据各个部分的时候，分散/聚集非常有用。比如，一条消息包含header和body两部分，你可以将他们放到不同的Buffer里。这样你就可以分开处理header和body了。
 */
public class FileReadTest {

    public static void main(String[] args) {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            InetSocketAddress address = new InetSocketAddress(8899);
            serverSocketChannel.socket().bind(address);
            int messageLength = 2 + 3 + 4;
            ByteBuffer[] buffers = new ByteBuffer[3];
            buffers[0] = ByteBuffer.allocate(2);
            buffers[1] = ByteBuffer.allocate(3);
            buffers[2] = ByteBuffer.allocate(4);
            SocketChannel socketChannel = serverSocketChannel.accept();
            while (true) {
                System.out.println("====================");
                int bytesRead = 0;
                while (bytesRead < messageLength) {
                    long r = socketChannel.read(buffers);
                    bytesRead += r;
                    System.out.println("bytesRead: " + bytesRead);
                    Arrays.asList(buffers).stream().map(buffer -> "position: " + buffer.position()
                            + ", limit : " + buffer.limit()).forEach(System.out::println);
                }
                Arrays.asList(buffers).forEach(buffer -> buffer.flip());

                long bytesWritten = 0;
                while (bytesWritten < messageLength) {
                    long r = socketChannel.write(buffers);
                    bytesWritten += r;
                }
                Arrays.asList(buffers).forEach(buffer -> buffer.clear());
                System.out.println("bytesRead:" + bytesRead + ",bytesWritted:"
                        + bytesWritten + " messageLength:" + messageLength);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }


    }
}
